﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using NamedBinaryTag;

namespace PaletteCalc
{
	class Program
	{
		static void Main(string[] args)
		{
			if ((args.Length < 3) || (args.Length % 2 == 0))
			{
				Console.WriteLine("Usage: PaletteCalc.exe <map1.dat> <mapshot1.png> [<map2.dat> <mapshot2.png> [...]] <output.csv>");
				Console.WriteLine("Where:");
				Console.WriteLine("	map*.dat	one of the Minecraft map data from the World data folder.");
				Console.WriteLine("	mapshot*.dat	a clipped ingame screenshot of the map.");
				Console.WriteLine("			The screenshot must be taken looking the foot to have a good map shot.");
				Console.WriteLine("			Better done over a Glowstone.");
				Console.WriteLine("	output.csv	name of the output file.");
				return;
			}
			Dictionary<Color, int>[] palette = new Dictionary<Color, int>[256];
			for (int i = 0; i < palette.Length; i++)
				palette[i] = new Dictionary<Color, int>();
			palette[0][Color.Transparent] = 0;
			TagFile source = new TagFile();
			for (int i = 0; i < args.Length - 1; i += 2)
			{
				using (System.IO.FileStream file = new System.IO.FileStream(args[i], System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
				{
					source.Load(file);
				}
				Bitmap capture = new Bitmap(args[i + 1]);
				short width = ((source.RootTag["data"] as TagCompound)["width"] as TagShort).Value;
				short height = ((source.RootTag["data"] as TagCompound)["height"] as TagShort).Value;
				float ratioX = (float)capture.Width / (float)width;
				float ratioY = (float)capture.Height / (float)height;
				byte[] data = ((source.RootTag["data"] as TagCompound)["colors"] as TagByteArray).Value;
				for (int x = 0; x < width; x++)
				{
					int dX = (int)Math.Round((x + 0.5) * ratioX);
					for (int y = 0; y < height; y++)
					{
						int dY = (int)Math.Round((y + 0.5) * ratioY);
						int index = data[y * width + x];
						if (index == 0)
						{
							Console.WriteLine("Unexplored: {0},{1}", x, y);
							continue;
						}
						Color dC = capture.GetPixel(dX, dY);
						if (!palette[index].ContainsKey(dC))
							palette[index][dC] = 0;
						palette[index][dC]++;
					}
				}
			}
			using (System.IO.StreamWriter writer = new System.IO.StreamWriter(args.Last(), false, Encoding.UTF8))
			{
				writer.WriteLine("Index;Colors");
				for (int i = 0; i < palette.Length; i++)
				{
					writer.Write(i);
					foreach (var item in from pair in palette[i] orderby pair.Value descending select pair)
					{
						writer.Write(string.Format(";#{0:X8};{1}", item.Key.ToArgb(), item.Value));
					}
					if (palette[i].Count == 0)
						writer.Write(";#{0:X8}", (0xFF << 24) + i * 0x10101);
					writer.WriteLine();
				}
			}
		}
	}
}
